﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ORMAC.UI.WPF.ViewModel;
using ORMAC.CodeGen;
using ORMAC.UI.WPF.Extensions;
using System.Windows.Shapes;
using System.IO;

namespace ORMAC.UI.WPF.Business
{
    /// <summary>
    /// contains ORMAC configuration fo a single Database
    /// </summary>
    public class ORMACDBConfiguration
    {
        private string nameSpace;
        /// <summary>
        /// the name space for all the generated classes for this datbase
        /// </summary>
        public string NameSpace
        {
            get { return nameSpace; }
            set { nameSpace = value; }
        }
        private string dBName;
        /// <summary>
        /// the name or the key to the current database
        /// </summary>
        public string DBName
        {
            get { return dBName; }
            set { dBName = value; }
        }

        private string connectionString;
        /// <summary>
        /// Database connection string
        /// </summary>
        public string ConnectionString
        {
            get
            {
                return connectionString;
            }
            set
            {
                connectionString = value;
            }
        }
        private List<DBObjectInfoEx> tables;
        /// <summary>
        /// the list of all database tables
        /// </summary>
        public List<DBObjectInfoEx> Tables
        {
            get
            {
                return tables;
            }
            set
            {
                tables = value;
            }
        }
        private List<DBObjectInfoEx> storedProcedures;
        /// <summary>
        /// list of all database stored procs
        /// </summary>
        public List<DBObjectInfoEx> StoredProcedures
        {
            get
            {
                return storedProcedures;
            }
            set
            {
                storedProcedures = value;
            }
        }
        /// <summary>
        /// loads the database schema into memory to be used by the code gen to create object model
        /// </summary>
        public void LoadDBObjects(){
            List<TableInfo> dbSchema = null;
            IDBSchema schema = new SQLShema();
            dbSchema = schema.RetrieveSchema<TableInfo>(this.connectionString);
            dbSchema = (from d in dbSchema orderby d.Name select d).ToList();
            List<DBObjectInfoEx> tempList = this.Tables;
            this.Tables = DBObjectInfoExtension.ToVM(dbSchema);
            //keep the previously selected objects
            if (this.Tables != null)
            {
                foreach (var dbObject in this.Tables)
                {
                    if (tempList != null)
                    {
                        var foundItem = tempList.Find(t => t.DBObject.Name == dbObject.DBObject.Name );
                        if (foundItem != null)
                            dbObject.IsSelected = foundItem.IsSelected;

                    }
                }
            }
                
            List<SProcInfo> sprocSchema = null;
            sprocSchema = schema.RetrieveSchema<SProcInfo>(this.connectionString);
            tempList = this.StoredProcedures;
            this.StoredProcedures = DBObjectInfoExtension.ToVM(sprocSchema);
            //keep the previously selected objects
            if (this.StoredProcedures != null)
            {
                foreach (var dbObject in this.StoredProcedures)
                {
                    if (tempList != null)
                    {
                        var foundItem = tempList.Find(t => t.DBObject.Name == dbObject.DBObject.Name);
                        if (foundItem != null)
                            dbObject.IsSelected = foundItem.IsSelected;
                    }
                }
            }
        }
        /// <summary>
        /// writes class data to a temporary file
        /// </summary>
        /// <param name="str">class text</param>
        /// <param name="objectName">the name of the class</param>
        /// <returns>generated file name</returns>
        private string WriteString2File(string str, string objectName)
        {
            string fileName = System.IO.Path.GetTempPath() + objectName + ".cs";
            FileStream f = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            StreamWriter w = new StreamWriter(f);
            w.Write(str);
            w.Close();
            f.Close();
            return fileName;
        }
        /// <summary>
        /// reads the database schema using ormac engine and generates temporary class files for each database object
        /// </summary>
        /// <returns>a list of generated file names</returns>
        public List<string> GenerateObjectFiles()
        {
            List<string> res=new List<string>();
            ICodeGenerator generator=new ORMAC.CodeGen.CodeGenerator();
            //Generate table classes
            foreach (DBObjectInfoEx table in Tables)
            {
                if (table.IsSelected)
                {
                    string classStr= generator.GenerateClass(this.ConnectionString, this.NameSpace, table.DBObject);
                    string fileName=WriteString2File(classStr,table.DBObject.Name);
                    res.Add(fileName);
                }
            }
            //Generate SP classes
            foreach (DBObjectInfoEx sp in StoredProcedures)
            {
                if (sp.IsSelected)
                {
                    string classStr = generator.GenerateClass(this.ConnectionString, this.NameSpace, sp.DBObject);
                    string fileName=WriteString2File(classStr,sp.DBObject.Name);
                    res.Add(fileName);
                }
            }
            //Generate repository class
            string repositoryClassStr=generator.GenerateRepository(this.ConnectionString, this.NameSpace);
            string repositoryFileName = WriteString2File(repositoryClassStr,"Repository");
            res.Add(repositoryFileName);
            return res;
        }

    }
}
